/**
 * 统一的剪贴板复制工具
 * 支持现代 Clipboard API 和降级方案
 * 解决运行时权限失效问题
 */

import { ElMessage } from 'element-plus'
import { createLogger } from './logger'

const componentLogger = createLogger('ClipboardUtil')

/**
 * 使用 execCommand 降级方案复制文本
 * @param {string} text - 要复制的文本
 * @returns {boolean} - 是否成功
 */
function fallbackCopyToClipboard(text) {
  const textArea = document.createElement('textarea')
  textArea.value = text
  
  // 使用绝对定位使 textarea 不可见，但保持在可交互区域
  textArea.style.position = 'fixed'
  textArea.style.left = '-999999px'
  textArea.style.top = '-999999px'
  textArea.style.opacity = '0'
  textArea.style.pointerEvents = 'none'
  
  document.body.appendChild(textArea)
  
  try {
    textArea.focus()
    textArea.select()
    
    // 移动端兼容（iOS Safari）
    if (navigator.userAgent.match(/ipad|iphone/i)) {
      const range = document.createRange()
      range.selectNodeContents(textArea)
      const selection = window.getSelection()
      selection.removeAllRanges()
      selection.addRange(range)
      textArea.setSelectionRange(0, 999999)
    }
    
    const successful = document.execCommand('copy')
    return successful
  } catch (err) {
    componentLogger.error('execCommand 复制失败:', err)
    return false
  } finally {
    document.body.removeChild(textArea)
  }
}

/**
 * 复制文本到剪贴板
 * @param {string} text - 要复制的文本
 * @param {string} label - 复制内容的标签（用于提示消息）
 * @param {boolean} showSuccessMessage - 是否显示成功提示，默认为 true
 * @returns {Promise<boolean>} - 返回复制是否成功
 */
export async function copyToClipboard(text, label = '内容', showSuccessMessage = true) {
  // 检查文本是否为空
  if (!text || text === '-' || text === '') {
    ElMessage.warning(`${label}为空，无法复制`)
    return false
  }

  let clipboardAPIFailed = false
  
  // 方法1：尝试使用现代 Clipboard API（需要安全上下文：HTTPS 或 localhost）
  if (navigator.clipboard && window.isSecureContext) {
    try {
      await navigator.clipboard.writeText(text)
      if (showSuccessMessage) {
        ElMessage.success(`${label}已复制到剪贴板`)
      }
      componentLogger.info(`${label}复制成功（Clipboard API）`)
      return true
    } catch (error) {
      // 权限被拒绝、页面失去焦点等情况下会失败
      clipboardAPIFailed = true
      componentLogger.warn(`Clipboard API 失败，尝试降级方案:`, error.message || error)
      
      // 如果是权限问题，记录详细信息
      if (error.name === 'NotAllowedError') {
        componentLogger.warn('剪贴板权限被拒绝，可能是页面失去焦点或用户拒绝授权')
      }
    }
  }

  // 方法2：降级方案 - 使用 document.execCommand
  // 在以下情况使用：
  // 1. Clipboard API 不可用
  // 2. 不在安全上下文中
  // 3. Clipboard API 调用失败
  try {
    const successful = fallbackCopyToClipboard(text)
    
    if (successful) {
      if (showSuccessMessage) {
        ElMessage.success(`${label}已复制到剪贴板`)
      }
      const method = clipboardAPIFailed ? 'Clipboard API失败后的降级方案' : 'execCommand 降级方案'
      componentLogger.info(`${label}复制成功（${method}）`)
      return true
    } else {
      throw new Error('execCommand 返回 false')
    }
  } catch (error) {
    componentLogger.error(`复制${label}失败（所有方法都失败）:`, error)
    ElMessage.error(`复制失败: 请手动复制内容`)
    return false
  }
}

/**
 * 复制 JSON 数据到剪贴板
 * @param {any} data - 要复制的数据对象
 * @param {string} label - 数据标签
 * @param {boolean} showSuccessMessage - 是否显示成功提示
 * @returns {Promise<boolean>} - 返回复制是否成功
 */
export async function copyJsonToClipboard(data, label = 'JSON', showSuccessMessage = true) {
  try {
    const jsonText = JSON.stringify(data, null, 2)
    return await copyToClipboard(jsonText, label, showSuccessMessage)
  } catch (error) {
    componentLogger.error(`格式化${label}失败:`, error)
    ElMessage.error(`格式化失败: ${error.message}`)
    return false
  }
}

export default {
  copyToClipboard,
  copyJsonToClipboard
}

